class SingleSocket {
  constructor() {
    // this.ip = '124.70.201.96'
    // 端口
    // this.port = 38803
    // url所需参数 - 用户名
    this.userAccount = ''
    // url所需参数 - 地磅机key
    this.machineKey = 'aaa'
    // 重连次数
    this.reconnectNum = 0
    // websocket实例
    this.ws = null
    // 重连定时器obj
    this.reconnectTimer = null
    // 避免重复连接
    this.lockReconnect = false
    // socket地址
    this.url = ''
    // 心跳标识code
    this.heartCode = 'HB'

    const _self = this
    this.heartCheck = {
      timeout: 1000 * 10,  // 3分钟
      timeoutObj: null,
      serverTimeoutObj: null,
      reset() {
        this.timeoutObj && clearTimeout(this.timeoutObj)
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
        return this
      },
      start() {
        this.timeoutObj = setTimeout(() => {
          // 这里发送一个心跳，后端收到后，返回一个心跳消息，
          // onmessage拿到返回的心跳就说明连接正常
          console.log(`心跳检测...`)
          _self.ws.send(_self.heartCode)
          this.serverTimeoutObj = setTimeout(() => { // 如果超过一定时间还没重置，说明后端主动断开了
            console.log(_self.ws.readyState, 'readyState')
            if (_self.ws.readyState !== 1) {
              // 如果onclose会执行reconnect，我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
              _self.ws.close()
            }
          }, this.timeout)
        }, this.timeout)
      }
    }
    // 页面onMessage监听回调
    this.onMsgCallback = null
    this.initCb = null
  }

  ReConnect() {
    this.reconnectNum++
    console.log("重连次数==", this.reconnectNum)
    // 10次都还没有连接上websocket，不再连了
    if (this.reconnectNum > 200) return;
    if (this.lockReconnect) return;
    this.lockReconnect = true
    // 没连接上会一直重连，设置延迟避免请求过多
    this.reconnectTimer && clearTimeout(this.reconnectTimer)
    this.reconnectTimer = setTimeout(() => {
      console.log(`socket: ${this.url} -- 执行断线重连...`)
      this.lockReconnect = false
      this.Init(null, this.userAccount, this.machineKey)
    }, 2000)
  }

  SetMsgCb(onMsgCb) {
    onMsgCb && (this.onMsgCallback = onMsgCb)
  }

  Send(data) {
    // TODO 需要加类型判断,只有obj才需要JSON.stringify
    this.ws.emit('send', JSON.stringify(data))
  }

  InitEventHandle() {
    // 监听后端推送过来的数据
    this.ws.onmessage = event => {
      this.ReconnectNum = 0

      console.log(event.data, 'event.data')
      if (this.heartCode !== event.data) {
        this.onMsgCallback && this.onMsgCallback(event)
      }
      // 如果获取到消息，心跳检测重置
      // 拿到任何消息都说明当前连接是正常的
      this.heartCheck.reset().start()
    }

    // 监听连接成功,需要心跳检测
    this.ws.onopen = () => {
      this.ReconnectNum = 0
      console.log("------------ websocket.onopen 连接成功 ------------")
      this.heartCheck.reset().start()
      this.initCb && this.initCb()
    }

    // 连接关闭,需要重连
    this.ws.onclose = () => {
      console.log("------------ websocket.onclose 连接关闭 ------------", this.ReconnectNum)
    }

    // 连接错误,需要重连
    this.ws.onerror = () => {
      console.log("  websocket.onclose  ", this.ReconnectNum)
      this.ReConnect()
    }
  }

  Close() {
    this.ws.close()
  }
}

export default SingleSocket
